"""
加密工具模块
"""
import logging
import hashlib
import base64
import os
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

logger = logging.getLogger(__name__)

class EncryptionUtils:
    """加密工具类"""
    
    @staticmethod
    def hash_password(password, salt=None):
        """
        哈希密码
        
        Args:
            password: 密码
            salt: 盐值 (可选)
        
        Returns:
            tuple: (哈希密码, 盐值)
        """
        try:
            # 如果没有提供盐值，生成一个新的
            if salt is None:
                salt = os.urandom(16)
            
            # 使用PBKDF2算法哈希密码
            kdf = PBKDF2HMAC(
                algorithm=hashes.SHA256(),
                length=32,
                salt=salt,
                iterations=100000,
            )
            
            # 计算哈希值
            key = kdf.derive(password.encode())
            
            return base64.b64encode(key).decode(), base64.b64encode(salt).decode()
        except Exception as e:
            logger.error(f"哈希密码失败: {str(e)}")
            raise
    
    @staticmethod
    def verify_password(password, hashed_password, salt):
        """
        验证密码
        
        Args:
            password: 密码
            hashed_password: 哈希密码
            salt: 盐值
        
        Returns:
            bool: 是否匹配
        """
        try:
            # 解码盐值
            salt_bytes = base64.b64decode(salt)
            
            # 使用相同的算法哈希密码
            kdf = PBKDF2HMAC(
                algorithm=hashes.SHA256(),
                length=32,
                salt=salt_bytes,
                iterations=100000,
            )
            
            # 计算哈希值
            key = kdf.derive(password.encode())
            
            # 比较哈希值
            return base64.b64encode(key).decode() == hashed_password
        except Exception as e:
            logger.error(f"验证密码失败: {str(e)}")
            return False
    
    @staticmethod
    def generate_key():
        """
        生成加密密钥
        
        Returns:
            str: 密钥
        """
        try:
            return Fernet.generate_key().decode()
        except Exception as e:
            logger.error(f"生成密钥失败: {str(e)}")
            raise
    
    @staticmethod
    def encrypt_text(text, key):
        """
        加密文本
        
        Args:
            text: 明文
            key: 密钥
        
        Returns:
            str: 密文
        """
        try:
            f = Fernet(key.encode() if isinstance(key, str) else key)
            encrypted = f.encrypt(text.encode() if isinstance(text, str) else text)
            return base64.b64encode(encrypted).decode()
        except Exception as e:
            logger.error(f"加密文本失败: {str(e)}")
            raise
    
    @staticmethod
    def decrypt_text(encrypted_text, key):
        """
        解密文本
        
        Args:
            encrypted_text: 密文
            key: 密钥
        
        Returns:
            str: 明文
        """
        try:
            f = Fernet(key.encode() if isinstance(key, str) else key)
            decrypted = f.decrypt(base64.b64decode(encrypted_text))
            return decrypted.decode()
        except Exception as e:
            logger.error(f"解密文本失败: {str(e)}")
            raise
    
    @staticmethod
    def md5(text):
        """
        计算MD5哈希值
        
        Args:
            text: 文本
        
        Returns:
            str: MD5哈希值
        """
        try:
            return hashlib.md5(text.encode() if isinstance(text, str) else text).hexdigest()
        except Exception as e:
            logger.error(f"计算MD5哈希值失败: {str(e)}")
            raise
    
    @staticmethod
    def sha256(text):
        """
        计算SHA256哈希值
        
        Args:
            text: 文本
        
        Returns:
            str: SHA256哈希值
        """
        try:
            return hashlib.sha256(text.encode() if isinstance(text, str) else text).hexdigest()
        except Exception as e:
            logger.error(f"计算SHA256哈希值失败: {str(e)}")
            raise
    
    @staticmethod
    def encrypt_connection_string(connection_string, key):
        """
        加密连接字符串
        
        Args:
            connection_string: 连接字符串
            key: 密钥
        
        Returns:
            str: 加密后的连接字符串
        """
        return EncryptionUtils.encrypt_text(connection_string, key)
    
    @staticmethod
    def decrypt_connection_string(encrypted_connection_string, key):
        """
        解密连接字符串
        
        Args:
            encrypted_connection_string: 加密后的连接字符串
            key: 密钥
        
        Returns:
            str: 连接字符串
        """
        return EncryptionUtils.decrypt_text(encrypted_connection_string, key)
    
    @staticmethod
    def mask_sensitive_data(text, mask_char='*', keep_prefix=2, keep_suffix=2):
        """
        掩码敏感数据
        
        Args:
            text: 文本
            mask_char: 掩码字符
            keep_prefix: 保留前缀长度
            keep_suffix: 保留后缀长度
        
        Returns:
            str: 掩码后的文本
        """
        try:
            if not text:
                return text
            
            text = str(text)
            text_len = len(text)
            
            if text_len <= keep_prefix + keep_suffix:
                return mask_char * text_len
            
            masked_len = text_len - keep_prefix - keep_suffix
            return text[:keep_prefix] + mask_char * masked_len + text[-keep_suffix:]
        except Exception as e:
            logger.error(f"掩码敏感数据失败: {str(e)}")
            raise